//******************************************************************************
//                         新人研修用サンプルプログラム
//******************************************************************************
// ファイル名 : practice12.c
//******************************************************************************

//--------------------------------
// インクルードファイル
//--------------------------------
#include <stdio.h>

//--------------------------------
// マクロ
//--------------------------------
/* 最大画像サイズ */
#define Y_SIZE 512
#define X_SIZE 512

//--------------------------------
// グローバル変数
//--------------------------------
/* BMPファイル用 */
short bfType;
long  bfSize;
short bfReserved1,
	  bfReserved2;
long  bfOffBits;
long  biSize,
	  biWidth,
	  biHeight;
short biPlanes,
	  biBitCount;
long  biCompression,
	  biSizeImage,
	  biXPelsPerMeter,
	  biYPelsPerMeter,
	  biClrUsed,
	  biClrImportant;
	  
unsigned char image_in[Y_SIZE][X_SIZE][3];	/* 入力カラー画像配列 */
unsigned char image_out[Y_SIZE][X_SIZE][3];	/* 出力カラー画像配列 */

//--------------------------------
// プロトタイプ宣言
//--------------------------------
void readBmp(char *filename, unsigned char image[Y_SIZE][X_SIZE][3]);
void mirror(unsigned char in[Y_SIZE][X_SIZE][3], unsigned char out[Y_SIZE][X_SIZE][3]);
void writeBmp(unsigned char image[Y_SIZE][X_SIZE][3], char *filename);

//***************************************************************************
// 機能名称 : メイン関数
//
// 関数名：int main()
// 引数　：なし
// 戻り値：常に0
// 機能　：ビットマップ画像をファイルから読み込み、上下左右を
// 　　　：反転させてからファイルに書き込む。
//***************************************************************************
int main(void){
	
	char input[100], output[100];

	printf("入力画像ファイル名(input.bmp)："); scanf("%s", input);
	printf("出力画像ファイル名(output.bmp)："); scanf("%s", output);

	/* 画像読み込み */
	readBmp(input, image_in);

	/* 画像反転処理 */
	mirror(image_in, image_out);

	/* 画像書き込み */
	writeBmp(image_out, output);
	
	return 0;
}

//***************************************************************************
// 機能名称 : ビットマップ画像データ読み込み関数
//
// 関数名   : void readBmp()
// 引数     : unsigned char image[Y_SIZE][X_SIZE][3]：画像イメージバッファ
//            char *filename：ビットマップファイルへのポインタ
// 戻り値   : なし
// 機能     : 24ビット-ビットマップデータ(BMPファイル)を
//            読み込み unsigned char型配列に格納する．
//            [注意] 画像の横幅は４の倍数であること！
//***************************************************************************
void readBmp(char *filename, unsigned char image[Y_SIZE][X_SIZE][3]){
	
	FILE *fp;
	int i, j, k;
	
	/* ファイルオープン */
	if ((fp = fopen(filename, "rb"))==NULL) {
		printf("readBmp: Open error!\n");
		exit(1);
	}
	printf("input file : %s\n", filename);

	/* ヘッダ情報読み込み */
	fread(&bfType, sizeof(bfType), 1, fp);
	fread(&bfSize, sizeof(bfSize), 1, fp);
	fread(&bfReserved1, sizeof(bfReserved1), 1, fp);
	fread(&bfReserved2, sizeof(bfReserved2), 1, fp);
	fread(&bfOffBits, sizeof(bfOffBits), 1, fp);
	fread(&biSize, sizeof(biSize), 1, fp);
	fread(&biWidth, sizeof(biWidth), 1, fp);
	fread(&biHeight, sizeof(biHeight), 1, fp);
	fread(&biPlanes, sizeof(biPlanes), 1, fp);
	fread(&biBitCount, sizeof(biBitCount), 1, fp);
	fread(&biCompression, sizeof(biCompression), 1, fp);
	fread(&biSizeImage, sizeof(biSizeImage), 1, fp);
	fread(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp);
	fread(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp);
	fread(&biClrUsed, sizeof(biClrUsed), 1, fp);
	fread(&biClrImportant, sizeof(biClrImportant), 1, fp);

	/* ビットマップデータ読み込み */
	for (i = 0; i < biHeight; i++){
		for (j = 0; j < biWidth; j++){
			for (k = 0; k < 3; k++){
				fread(&image[i][j][2-k], 1, 1, fp);
			}
		}
	}
	
	fclose(fp);
}

//***************************************************************************
// 機能名称 : 鏡像を作る(左右、上下反転)
//
// 関数名   : void mirror()
// 引数     : unsigned char in[Y_SIZE][X_SIZE][3]  :入力画像バッファ
//            unsigned char out[Y_SIZE][X_SIZE][3] :出力画像バッファ
// 戻り値   : なし
// 機能     : 
//***************************************************************************
void mirror(unsigned char in[Y_SIZE][X_SIZE][3], unsigned char out[Y_SIZE][X_SIZE][3]){
	int i, j, k;

	for (i = 0; i < biHeight; i++){
		for (j = 0; j < biWidth; j++){
			for (k = 0; k < 3; k++){
				out[i][j][k] = in[biHeight-1-i][biWidth-1-j][k];
			}
		}
	}
}

//***************************************************************************
// 機能名称 : ビットマップ画像データ書き込み関数
//
// 関数名   : void writeBmp()
// 引数     : unsigned char image[Y_SIZE][X_SIZE][3]：画像イメージバッファ
//            char *filename：ビットマップファイルへのポインタ
// 戻り値   : なし
// 機能     : unsigned char型配列に格納された24ビット-ビットマップデータ
//            をBMPファイルに出力する
//            [注意] 画像の横幅は４の倍数であること！
//***************************************************************************
void writeBmp(unsigned char image[Y_SIZE][X_SIZE][3], char *filename){
	
	FILE *fp;
	int i, j, k;
	
	/* ファイルオープン */
	if ((fp = fopen(filename, "wb"))==NULL) {
		printf("writeBmp: Open error!\n");
		exit(1);
	}
	printf("output file : %s\n", filename);

	/* ビットマップファイルヘッダ情報生成 */
	fwrite(&bfType, sizeof(bfType), 1, fp);
	fwrite(&bfSize, sizeof(bfSize), 1, fp);
	fwrite(&bfReserved1, sizeof(bfReserved1), 1, fp);
	fwrite(&bfReserved2, sizeof(bfReserved2), 1, fp);
	fwrite(&bfOffBits, sizeof(bfOffBits), 1, fp);
	fwrite(&biSize, sizeof(biSize), 1, fp);
	fwrite(&biWidth, sizeof(biWidth), 1, fp);
	fwrite(&biHeight, sizeof(biHeight), 1, fp);
	fwrite(&biPlanes, sizeof(biPlanes), 1, fp);
	fwrite(&biBitCount, sizeof(biBitCount), 1, fp);
	fwrite(&biCompression, sizeof(biCompression), 1, fp);
	fwrite(&biSizeImage, sizeof(biSizeImage), 1, fp);
	fwrite(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp);
	fwrite(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp);
	fwrite(&biClrUsed, sizeof(biClrUsed), 1, fp);
	fwrite(&biClrImportant, sizeof(biClrImportant), 1, fp);

	/* ビットマップデータ生成 */
	for(i = 0; i < biHeight; i++){
		for(j = 0; j < biWidth; j++){
			for(k = 0; k < 3; k++){
				fwrite(&image[i][j][2-k], 1, 1, fp);
			}
		}
	}
	fclose(fp);
}
